package com.vgemv.jsutilitysdk.file;


import android.content.Context;
import android.os.Environment;
import android.os.FileUtils;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import static android.os.Environment.DIRECTORY_DOCUMENTS;

import com.vgemv.jsutilitysdk.log.JsLogEvent;


/**
 * 功能:方便UI操作
 */
public class JsFileManager {

    private static JsFileManager _sharedInstance;

    private Context mContext;
    private boolean mb_isInitialed;
    public String mstr_appName;
    public static String TAG = JsFileManager.class.getSimpleName();

    public static JsFileManager sharedInstance() {
        return _sharedInstance;
    }

    //初始化信息,只初始化一次.
    public static void initClass(Context context,String appName) {
        if(_sharedInstance == null) {
            _sharedInstance = new JsFileManager();
            _sharedInstance.mContext = context;
            _sharedInstance.mstr_appName = appName;
            _sharedInstance.mb_isInitialed = true;
        }
    }

    //指定文件夹下的所有文件
    public static ArrayList<String> al_dirAllFilePath;


    /**
     * 公共Doc目录中创建并返回app名字命名的目录,并返回该路径.
     * @return
     */
    public String appDirPathInPubDoc () {
        String storageRootDirPath = Environment.getExternalStoragePublicDirectory(DIRECTORY_DOCUMENTS).getAbsolutePath();
        String appDocDirPath = String.format("%s/%s", storageRootDirPath, mstr_appName);
        File file_storageDir = new File(appDocDirPath);
        if (!file_storageDir.exists()) {
            if (!file_storageDir.mkdir()) {
                throw new AssertionError("JsFileManager create log file failed!");
            }
        }
        return appDocDirPath;
    }

    public String filePathInAppDocDirWithName(String fileName) {
        return String.format("%s/%s",appDirPathInPubDoc(),fileName);
    }

    public  String docPathInAppInnerPath(String appName) {
        String storageRootDirPath = mContext.getExternalFilesDir(null).getAbsolutePath();
        String appDocDirPath = String.format("%s/%s", storageRootDirPath, appName);
        File file_storageDir = new File(appDocDirPath);
        if (!file_storageDir.exists()) {
            if (!file_storageDir.mkdir()) {
                throw new AssertionError("JsFileManager create log file failed!");
            }
        }
        return appDocDirPath;
    }

    /*
    appFilePath:
     /storage/emulated/0/Android/data/com.vgemv.appName/files
     */
    public String appFileDir() {
        return mContext.getExternalFilesDir(null).getAbsolutePath();
    }

    // storage/emulated/0/Android/data/com.vgemv.appName/files/log
    public String logDirPathInAppFilePath() {
        String externalFilesDir = null;
        try {
             externalFilesDir = mContext.getExternalFilesDir(null).getAbsolutePath();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        String logDirPath = String.format("%s/%s", externalFilesDir, "log");
        File file_logDir = new File(logDirPath);
        if (!file_logDir.exists()) {
            if (!file_logDir.mkdir()) {
                throw new AssertionError("GajFileManager create log file failed!");
            }
        }
        return logDirPath;
    }



    /** 删除文件，可以是文件或文件夹
     * @param itemPath 要删除的文件夹或文件名
     * @return 删除成功返回true，否则返回false
     */
    public static boolean deleteItem(String itemPath) {
        File file = new File(itemPath);
            if (file.isFile()) {
                return deleteSingleFile(itemPath);
            }
            else {
                return deleteDir(itemPath);
            }
        }

    public static boolean deleteDir(String itemPath) {
        return clearDir(itemPath,true);
    }


    /** 删除单个文件
     * @param filePath$Name 要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteSingleFile(String filePath$Name) {
        File file = new File(filePath$Name);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        }
        else {
            return false;
        }
    }

    /** 删除目录及目录下的文件
     * @param dirPath 要删除的目录的文件路径
     * @isDelete      是否删除.
     * @return        目录删除成功返回true，否则返回false
     * 要删除文件夹,必须保证这个文件夹是空的,才能删除.所以必须依次删除叶子节点.
     */
    public static boolean clearDir(String dirPath, boolean isDelete) {
        // 如果dir不以文件分隔符结尾，自动添加文件分隔符
        if (!dirPath.endsWith(File.separator))
            dirPath = dirPath + File.separator;
        File dirFile = new File(dirPath);
        // 如果dir对应的文件不存在，或者不是一个目录，则退出
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            return false;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        for (File file : files) {
            // 删除子文件
            if (file.isFile()) {
                flag = deleteSingleFile(file.getAbsolutePath());
                if (!flag)
                    break;
            }
            // 删除子目录
            else  {
                flag = clearDir(file
                        .getAbsolutePath(),true);
                if (!flag)
                    break;
            }
        }
        if (!flag) {
            return false;
        }
        // 删除当前目录
        if (isDelete) {
            if(dirFile.delete()) {
                return true;
            }
            else {
                return false;
            }
        }
        return true;
    }


    //搜索目录，扩展名，是否进入子文件夹
    public static ArrayList<String> allFilesInDir(String Path, String Extension, boolean IsIterative) {
//        File[] files = new File(Path).listFiles();
//        File f;
//        if(files == null)
//        {
//            Toast.makeText(MyListView.this, Path+"is empty",Toast.LENGTH_LONG);
//            return;
//        }
//        for (int i = 0; i < files.length; i++)
//        {
//            f = files[i];
//            if(!f.canRead())
//            {
//                Toast.makeText(MyListView.this, Path+"can not read",Toast.LENGTH_LONG);
//                return;
//            }
//            if (f.isFile())
//            {
//                if (f.getName().contains(Extension))  //判断扩展名
//                {
//                    Log.v(TAG,f.getPath());
//                    paths.add(f.getPath());
//                }
//            }
//            else if (f.isDirectory())
//                GetFiles(f.getPath(), Extension, IsIterative);
//        }
        return null;
    }

    /**
     * 保证一个文件夹下面只有不超过fileCount个数的文件,如果超过,删除早的文件.
     * @param dirPath
     * @param fileCount
     */
    public static void limitDirFileCount(String dirPath,int fileCount) {
        File file_dir = new File(dirPath);
        if(!file_dir.exists()) {
            return;
        }
        File[] items = file_dir.listFiles();
        if(items.length < fileCount) {
            return;
        }
        ArrayList<File> al = new ArrayList<>();
        for (File file : items) {
            if(file.isFile()) {
                al.add(file);
            }
        }
        if(al.size() < fileCount) {
            return;
        }

        //按照修改时间排序,时间大的在前面?
        Comparator<File> comparator = new Comparator<File>() {
            @Override
            public int compare(File file, File t1) {
                return (int) (file.lastModified() - t1.lastModified());
            }
        };
        Collections.sort(al,comparator);
        //验证排序结果:
        for(int i = 0;i< al.size();i++) {
            File file = al.get(i);
            String info = String.format("The %d file,name:%d,modify time:%l",i,file.getName(),file.lastModified());
            Log.d(TAG,info);
        }
//        for(int i = fileCount -1; i<al.size() ;i++) {
//            File file = al.get(i);
//            file.delete();
//        }
    }

    /**
     * 一次性读取文件内容.
     * @param file
     * @return
     */
    public static String readFileContentRapidly(File file) {
        try {
            FileInputStream is = new FileInputStream(file);
            int iAvail = is.available();
            byte[] bytes = new byte[iAvail];
            //read,是以内存为主体,内存从文件读取数据.
            is.read(bytes);
            return new String(bytes);
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return "";
    }

    private static final String[][] MIME_MapTable = {
            // {后缀名， MIME类型}
            { ".3gp", "video/3gpp" },
            { ".apk", "application/vnd.android.package-archive" },
            { ".asf", "video/x-ms-asf" }, { ".avi", "video/x-msvideo" },
            { ".bin", "application/octet-stream" }, { ".bmp", "image/bmp" },
            { ".c", "text/plain" }, { ".class", "application/octet-stream" },
            { ".conf", "text/plain" }, { ".cpp", "text/plain" },
            { ".doc", "application/msword" },
            { ".exe", "application/octet-stream" }, { ".gif", "image/gif" },
            { ".gtar", "application/x-gtar" }, { ".gz", "application/x-gzip" },
            { ".h", "text/plain" }, { ".htm", "text/html" },
            { ".html", "text/html" }, { ".jar", "application/java-archive" },
            { ".java", "text/plain" }, { ".jpeg", "image/jpeg" },
            { ".jpg", "image/jpeg" }, { ".js", "application/x-javascript" },
            { ".log", "text/plain" }, { ".m3u", "audio/x-mpegurl" },
            { ".m4a", "audio/mp4a-latm" }, { ".m4b", "audio/mp4a-latm" },
            { ".m4p", "audio/mp4a-latm" }, { ".m4u", "video/vnd.mpegurl" },
            { ".m4v", "video/x-m4v" }, { ".mov", "video/quicktime" },
            { ".mp2", "audio/x-mpeg" }, { ".mp3", "audio/x-mpeg" },
            { ".mp4", "video/mp4" },
            { ".mpc", "application/vnd.mpohun.certificate" },
            { ".mpe", "video/mpeg" }, { ".mpeg", "video/mpeg" },
            { ".mpg", "video/mpeg" }, { ".mpg4", "video/mp4" },
            { ".mpga", "audio/mpeg" },
            { ".msg", "application/vnd.ms-outlook" }, { ".ogg", "audio/ogg" },
            { ".pdf", "application/pdf" }, { ".png", "image/png" },
            { ".pps", "application/vnd.ms-powerpoint" },
            { ".ppt", "application/vnd.ms-powerpoint" },
            { ".prop", "text/plain" },
            { ".rar", "application/x-rar-compressed" },
            { ".rc", "text/plain" }, { ".rmvb", "audio/x-pn-realaudio" },
            { ".rtf", "application/rtf" }, { ".sh", "text/plain" },
            { ".tar", "application/x-tar" },
            { ".tgz", "application/x-compressed" }, { ".txt", "text/plain" },
            { ".wav", "audio/x-wav" }, { ".wma", "audio/x-ms-wma" },
            { ".wmv", "audio/x-ms-wmv" },
            { ".wps", "application/vnd.ms-works" },
//            {".xml", "text/xml"},
            { ".xml", "text/plain" }, { ".z", "application/x-compress" },
            { ".zip", "application/zip" }, { "", "*/*" }
    };

    public static String getMIMEType(File file) {
        String type="*/*";
        String fName = file.getName();
        //获取后缀名前的分隔符"."在fName中的位置。
        int dotIndex = fName.lastIndexOf(".");
        if(dotIndex < 0)
            return type;
        /* 获取文件的后缀名 */
        String fileType = fName.substring(dotIndex,fName.length()).toLowerCase();
        if("".equals(fileType))
            return type;
        //在MIME和文件类型的匹配表中找到对应的MIME类型。
        for(int i = 0; i< MIME_MapTable.length; i++){
            if(fileType.equals(MIME_MapTable[i][0]))
                type = MIME_MapTable[i][1];
        }
        return type;
    }

    public static void appendContent(File file,String content) {
            FileWriter fw = null;
            try {
                fw = new FileWriter(file.getAbsolutePath(),true);
                fw.append(content);
                fw.flush();
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
}